home *** CD-ROM | disk | FTP | other *** search
/ Sun Solutions 1997 April to September / Sun Solutions CD - APR '97 - SEP '97 (704-3778-12 Rev. H)(Sun Microsystems, Inc.)(1997).iso / products / bin / httpd / src / http_include.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  19KB  |  648 lines

  1. /*
  2.  * http_include.c: Handles the server-parsed HTML documents
  3.  *
  4.  * All code contained herein is covered by the Copyright as distributed
  5.  * in the README file in the main directory of the distribution of 
  6.  * NCSA HTTPD.
  7.  * 
  8.  * Based on NCSA HTTPd 1.3 by Rob McCool
  9.  * 
  10.  *  04-07-95 blong
  11.  *    Fixes bug where substrings of the environment variable might be 
  12.  *    included first as suggested by David Robinson (drtr@ast.cam.ac.uk)
  13.  */
  14.  
  15. #include "httpd.h"
  16.  
  17. #define STARTING_SEQUENCE "<!--#"
  18. #define ENDING_SEQUENCE "-->"
  19. #define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
  20. #define DEFAULT_TIME_FORMAT "%A, %d-%b-%y %T %Z"
  21. #define SIZEFMT_BYTES 0
  22. #define SIZEFMT_KMG 1
  23.  
  24. /* These are stored statically so that they can be reformatted quickly */
  25. static time_t date,lm;
  26.  
  27. /* ------------------------ Environment function -------------------------- */
  28.  
  29. #define NUM_INCLUDE_VARS 5
  30.  
  31. char **add_include_vars(char **env,char *file, char *path_args, char *args, 
  32.                         char *timefmt,FILE *out)
  33. {
  34.     int x;
  35.     struct stat finfo;
  36.     char ufile[HUGE_STRING_LEN];
  37.     char *t;
  38.  
  39.     if(!(env = new_env(env,NUM_INCLUDE_VARS,&x)))
  40.         die(NO_MEMORY,"add_include_vars",out);
  41.     date = time(NULL);
  42.     env[x++] = make_env_str("DATE_LOCAL",ht_time(date,timefmt,0),out);
  43.     env[x++] = make_env_str("DATE_GMT",ht_time(date,timefmt,1),out);
  44.  
  45.     if(stat(file,&finfo) != -1) {
  46.         lm = finfo.st_mtime;
  47.         env[x++] = make_env_str("LAST_MODIFIED",ht_time(lm,timefmt,0),out);
  48.     }
  49.     strcpy(ufile,file);
  50.     unmunge_name(ufile);
  51.     env[x++] = make_env_str("DOCUMENT_URI",ufile,out);
  52.     if(t = strrchr(ufile,'/'))
  53.         ++t;
  54.     else
  55.         t = ufile;
  56.     env[x++] = make_env_str("DOCUMENT_NAME",t,out);
  57.     env[x] = NULL;
  58.     return env;
  59. }
  60.  
  61. #define GET_CHAR(f,c,r) \
  62.  { \
  63.    int i = getc(f); \
  64.    if(feof(f) || ferror(f) || (i == -1)) { \
  65.         fclose(f); \
  66.         return r; \
  67.    } \
  68.    c = (char)i; \
  69.  }
  70.  
  71. /* --------------------------- Parser functions --------------------------- */
  72.  
  73. int find_string(FILE *in,char *str, FILE *out) {
  74.     int x,l=strlen(str),p;
  75.     char c;
  76.  
  77.     p=0;
  78.     while(1) {
  79.         GET_CHAR(in,c,1);
  80.         if(c == str[p]) {
  81.             if((++p) == l)
  82.                 return 0;
  83.         }
  84.         else {
  85.             if(out) {
  86.                 if(p) {
  87.                     for(x=0;x<p;x++) {
  88.                         putc(str[x],out);
  89.                         ++bytes_sent;
  90.                     }
  91.                 }
  92.                 putc(c,out);
  93.                 ++bytes_sent;
  94.             }
  95.             p=0;
  96.         }
  97.     }
  98. }
  99.  
  100. char *get_tag(FILE *in, char *tag) {
  101.     char *t = tag, *tag_val, c;
  102.     int n;
  103.  
  104.     n = 0;
  105.     while(1) {
  106.         GET_CHAR(in,c,NULL);
  107.         if(!isspace(c)) break;
  108.     }
  109.     /* problem: this drops tags starting with - or -- (tough s***) */
  110.     if(c == '-') {
  111.         GET_CHAR(in,c,NULL);
  112.         if(c == '-') {
  113.             GET_CHAR(in,c,NULL);
  114.             if(c == '>') {
  115.                 strcpy(tag,"done");
  116.                 return tag;
  117.             }
  118.         }
  119.     }
  120.     /* this parser is very rigid, needs quotes around value and no spaces */
  121.     while(1) {
  122.         if(++n == MAX_STRING_LEN) {
  123.             t[MAX_STRING_LEN - 1] = '\0';
  124.             return NULL;
  125.         }
  126.         if((*t = c) == '\\') {
  127.             GET_CHAR(in,c,NULL);
  128.             *t = c;
  129.         } else if(*t == '=') {
  130.             *t++ = '\0';
  131.             tag_val = t;
  132.             GET_CHAR(in,c,NULL);
  133.             if(c == '\"') {
  134.                 while(1) {
  135.                     GET_CHAR(in,c,NULL);
  136.                     if(++n == MAX_STRING_LEN) {
  137.                         t[MAX_STRING_LEN - 1] = '\0';
  138.                         return NULL;
  139.                     }
  140.                     if((*t = c) == '\\') {
  141.                         GET_CHAR(in,c,NULL);
  142.                         *t = c;
  143.                     } else if(*t == '\"') {
  144.                         *t = '\0';
  145.                         return tag_val;
  146.                     }
  147.                     ++t;
  148.                 }
  149.             } else 
  150.                 return NULL;
  151.         }
  152.         ++t;
  153.         GET_CHAR(in,c,NULL);
  154.     }
  155. }
  156.  
  157. int get_directive(FILE *in,char *d) {
  158.     char c;
  159.  
  160.     /* skip initial whitespace */
  161.     while(1) {
  162.         GET_CHAR(in,c,1);
  163.         if(!isspace(c))
  164.             break;
  165.     }
  166.     /* now get directive */
  167.     while(1) {
  168.         *d++ = c;
  169.         GET_CHAR(in,c,1);
  170.         if(isspace(c))
  171.             break;
  172.     }
  173.     *d = '\0';
  174.     return 0;
  175. }
  176.  
  177. /* --------------------------- Action handlers ---------------------------- */
  178.  
  179.  
  180. void send_parsed_content(char *file, FILE *f, FILE *fd, 
  181.                          char *path_args, char *args,
  182.                          char **env,int noexec);
  183.  
  184. int send_included_file(char *file, FILE *out, char **env, char *fn) 
  185. {
  186.     FILE *f;
  187.     struct stat finfo;
  188.     int allow;
  189.     char op;
  190.  
  191.     if(stat(file,&finfo) == -1)
  192.         return -1;
  193.     evaluate_access(file,&finfo,M_GET,&allow,&op,out);
  194.     if(!allow)
  195.         return -1;
  196.     set_content_type(file);
  197.     if((op & OPT_INCLUDES) && (!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
  198.         if(!(f = fopen(file,"r")))
  199.             return -1;
  200.         send_parsed_content(file,f,out,"","",env,op & OPT_INCNOEXEC);
  201.         chdir_file(fn); /* grumble */
  202.     }
  203.     else if(!strcmp(content_type,CGI_MAGIC_TYPE))
  204.         return -1;
  205.     else {
  206.         if(!(f=fopen(file,"r")))
  207.             return -1;
  208.         send_fd(f,out,NULL);
  209.     }
  210.     fclose(f);
  211.     return 0;
  212. }
  213.  
  214. int handle_include(FILE *in, FILE *out, char *fn, char **env, char *error) {
  215.     char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
  216.     char *tag_val;
  217.  
  218.     while(1) {
  219.         if(!(tag_val = get_tag(in,tag)))
  220.             return 1;
  221.         if(!strcmp(tag,"file")) {
  222.             char dir[MAX_STRING_LEN],to_send[MAX_STRING_LEN];
  223.  
  224.             getparents(tag_val); /* get rid of any nasties */
  225.             getwd(dir);
  226.             make_full_path(dir,tag_val,to_send);
  227.             if(send_included_file(to_send,out,env,fn)) {
  228.                 sprintf(errstr,"unable to include %s in parsed file %s",
  229.                         tag_val, fn);
  230.                 log_error_noclose(errstr);
  231.                 bytes_sent += fprintf(out,"%s",error);
  232.             }            
  233.         } 
  234.         else if(!strcmp(tag,"virtual")) {
  235.             if(translate_name(tag_val,out) != STD_DOCUMENT) {
  236.                 bytes_sent += fprintf(out,"%s",error);
  237.                 log_error_noclose(errstr);
  238.             }  
  239.             else if(send_included_file(tag_val,out,env,fn)) {
  240.                 sprintf(errstr,"unable to include %s in parsed file %s",
  241.                         tag_val, fn);
  242.                 log_error_noclose(errstr);
  243.                 bytes_sent += fprintf(out,"%s",error);
  244.             }
  245.         } 
  246.         else if(!strcmp(tag,"done"))
  247.             return 0;
  248.         else {
  249.             sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,fn);
  250.             log_error_noclose(errstr);
  251.             bytes_sent += fprintf(out,"%s",error);
  252.         }
  253.     }
  254. }
  255.  
  256. int handle_echo(FILE *in, FILE *out, char *file, char *error, char **env) {
  257.     char tag[MAX_STRING_LEN];
  258.     char *tag_val;
  259.  
  260.     while(1) {
  261.         if(!(tag_val = get_tag(in,tag)))
  262.             return 1;
  263.         if(!strcmp(tag,"var")) {
  264.             int x,i,len;
  265.  
  266.         len = strlen(tag_val); 
  267.             for(x=0;env[x] != NULL; x++) {
  268.                 i = ind(env[x],'=');
  269.                 if((i == len) && !(strncmp(env[x],tag_val,i))) {
  270.                     bytes_sent += fprintf(out,"%s",&env[x][i+1]);
  271.                     break;
  272.                 }
  273.             }
  274.             if(!env[x]) bytes_sent += fprintf(out,"(none)");
  275.         } else if(!strcmp(tag,"done"))
  276.             return 0;
  277.         else {
  278.             char errstr[MAX_STRING_LEN];
  279.             sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
  280.             log_error_noclose(errstr);
  281.             bytes_sent += fprintf(out,"%s",error);
  282.         }
  283.     }
  284. }
  285.  
  286. int include_cgi(char *s, char *pargs, char *args, char **env, FILE *out) 
  287. {
  288.     char op,d[HUGE_STRING_LEN];
  289.     int allow,check_cgiopt;
  290.     struct stat finfo;
  291.  
  292.     getparents(s);
  293.     if(s[0] == '/') {
  294.         strcpy(d,s);
  295.         if(translate_name(d,out) != SCRIPT_CGI)
  296.             return -1;
  297.         check_cgiopt=0;
  298.     } else {
  299.         char dir[MAX_STRING_LEN];
  300.         getwd(dir);
  301.         make_full_path(dir,s,d);
  302.         check_cgiopt=1;
  303.     }
  304.     /* No hardwired path info or query allowed */
  305.     if(stat(d,&finfo) == -1)
  306.         return -1;
  307.  
  308.     evaluate_access(d,&finfo,M_GET,&allow,&op,out);
  309.     if((!allow) || (check_cgiopt && (!(op & OPT_EXECCGI))))
  310.         return -1;
  311.  
  312.     if(cgi_stub("GET",d,pargs,args,env,&finfo,-1,out) == REDIRECT_URL)
  313.         bytes_sent += fprintf(out,"<A HREF=\"%s\">%s</A>",location,location);
  314.     return 0;
  315. }
  316.  
  317. static int ipid;
  318. void kill_include_child() {
  319.     char errstr[MAX_STRING_LEN];
  320.     sprintf(errstr,"killing command process %d",ipid);
  321.     log_error_noclose(errstr);
  322.     kill(ipid,SIGKILL);
  323.     waitpid(ipid,NULL,0);
  324. }
  325.  
  326. int include_cmd(char *s, char *pargs, char *args, char **env, FILE *out) {
  327.     int p[2],x;
  328.     FILE *f;
  329.  
  330.     if(pipe(p) == -1)
  331.         die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
  332.     if((ipid = fork()) == -1)
  333.         die(SERVER_ERROR,"httpd: could not fork new process",out);
  334.     if(!ipid) {
  335.         char *argv0;
  336.  
  337.         if(pargs[0] || args[0]) {
  338.             if(!(in_headers_env = new_env(in_headers_env,4,&x)))
  339.                 return -1;
  340.             if(pargs[0]) {
  341.                 char p2[HUGE_STRING_LEN];
  342.                 
  343.                 escape_shell_cmd(pargs);
  344.                 in_headers_env[x++] = make_env_str("PATH_INFO",pargs,out);
  345.                 strcpy(p2,pargs);
  346.                 translate_name(p2,out);
  347.                 in_headers_env[x++] = make_env_str("PATH_TRANSLATED",p2,out);
  348.             }
  349.             if(args[0]) {
  350.                 in_headers_env[x++] = make_env_str("QUERY_STRING",args,out);
  351.                 unescape_url(args);
  352.                 escape_shell_cmd(args);
  353.                 in_headers_env[x++] = make_env_str("QUERY_STRING_UNESCAPED",args,out);
  354.             }
  355.             in_headers_env[x] = NULL;
  356.         }
  357.  
  358.         close(p[0]);
  359.         if(p[1] != STDOUT_FILENO) {
  360.             dup2(p[1],STDOUT_FILENO);
  361.             close(p[1]);
  362.         }
  363.         error_log2stderr();
  364.         if(!(argv0 = strrchr(SHELL_PATH,'/')))
  365.             argv0=SHELL_PATH;
  366.         if(execle(SHELL_PATH,argv0,"-c",s,(char *)0,in_headers_env) == -1) {
  367.             fprintf(stderr,"httpd: exec of %s failed, errno is %d\n",
  368.                     SHELL_PATH,errno);
  369.             exit(1);
  370.         }
  371.     }
  372.     close(p[1]);
  373.     if(!(f=fdopen(p[0],"r"))) {
  374.         waitpid(ipid,NULL,0);
  375.         return -1;
  376.     }
  377.     send_fd(f,out,kill_include_child);
  378.     fclose(f);
  379.     waitpid(ipid,NULL,0);
  380.     return 0;
  381. }
  382.  
  383.  
  384. int handle_exec(FILE *in, FILE *out, char *file, char *path_args, char *args,
  385.                 char *error, char **env)
  386. {
  387.     char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
  388.     char *tag_val;
  389.  
  390.     while(1) {
  391.         if(!(tag_val = get_tag(in,tag)))
  392.             return 1;
  393.         if(!strcmp(tag,"cmd")) {
  394.             if(include_cmd(tag_val,path_args,args,env,out) == -1) {
  395.                 sprintf(errstr,"invalid command exec %s in %s",tag_val,file);
  396.                 log_error_noclose(errstr);
  397.                 bytes_sent += fprintf(out,"%s",error);
  398.             }
  399.             /* just in case some stooge changed directories */
  400.             chdir_file(file);
  401.         } 
  402.         else if(!strcmp(tag,"cgi")) {
  403.             if(include_cgi(tag_val,path_args,args,env,out) == -1) {
  404.                 sprintf(errstr,"invalid CGI ref %s in %s",tag_val,file);
  405.                 log_error_noclose(errstr);
  406.                 bytes_sent += fprintf(out,"%s",error);
  407.             }
  408.             /* grumble groan */
  409.             chdir_file(file);
  410.         }
  411.         else if(!strcmp(tag,"done"))
  412.             return 0;
  413.         else {
  414.             char errstr[MAX_STRING_LEN];
  415.             sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
  416.             log_error_noclose(errstr);
  417.             bytes_sent += fprintf(out,"%s",error);
  418.         }
  419.     }
  420.  
  421. }
  422.  
  423. int handle_config(FILE *in, FILE *out, char *file, char *error, char *tf,
  424.                   int *sizefmt, char **env) {
  425.     char tag[MAX_STRING_LEN];
  426.     char *tag_val;
  427.  
  428.     while(1) {
  429.         if(!(tag_val = get_tag(in,tag)))
  430.             return 1;
  431.         if(!strcmp(tag,"errmsg"))
  432.             strcpy(error,tag_val);
  433.         else if(!strcmp(tag,"timefmt")) {
  434.             strcpy(tf,tag_val);
  435.             /* Replace DATE* and LAST_MODIFIED (they should be first) */
  436.         replace_env_str(in_headers_env, "DATE_LOCAL", ht_time(date,tf,0), out);
  437.         replace_env_str(in_headers_env, "DATE_GMT", ht_time(date,tf,1), out);
  438.         replace_env_str(in_headers_env, "LAST_MODIFIED", ht_time(lm,tf,0), out);
  439.         }
  440.         else if(!strcmp(tag,"sizefmt")) {
  441.             if(!strcmp(tag_val,"bytes"))
  442.                 *sizefmt = SIZEFMT_BYTES;
  443.             else if(!strcmp(tag_val,"abbrev"))
  444.                 *sizefmt = SIZEFMT_KMG;
  445.         } 
  446.         else if(!strcmp(tag,"done"))
  447.             return 0;
  448.         else {
  449.             char errstr[MAX_STRING_LEN];
  450.             sprintf(errstr,"unknown parameter %s to tag config in %s",
  451.                     tag,file);
  452.             log_error_noclose(errstr);
  453.             bytes_sent += fprintf(out,"%s",error);
  454.         }
  455.     }
  456. }
  457.  
  458.  
  459.  
  460. int find_file(FILE *out, char *file, char *directive, char *tag, 
  461.               char *tag_val, struct stat *finfo, char *error)
  462. {
  463.     char errstr[MAX_STRING_LEN], dir[MAX_STRING_LEN], to_send[MAX_STRING_LEN];
  464.  
  465.     if(!strcmp(tag,"file")) {
  466.         getparents(tag_val); /* get rid of any nasties */
  467.         getwd(dir);
  468.         make_full_path(dir,tag_val,to_send);
  469.         if(stat(to_send,finfo) == -1) {
  470.             sprintf(errstr,
  471.                     "unable to get information about %s in parsed file %s",
  472.                     to_send,file);
  473.             log_error_noclose(errstr);
  474.             bytes_sent += fprintf(out,"%s",error);
  475.             return -1;
  476.         }
  477.         return 0;
  478.     }
  479.     else if(!strcmp(tag,"virtual")) {
  480.         if(translate_name(tag_val,out) != STD_DOCUMENT) {
  481.             bytes_sent += fprintf(out,"%s",error);
  482.             log_error_noclose(errstr);
  483.         }  
  484.         else if(stat(tag_val,finfo) == -1) {
  485.             sprintf(errstr,
  486.                     "unable to get information about %s in parsed file %s",
  487.                     to_send,file);
  488.             log_error_noclose(errstr);
  489.             bytes_sent += fprintf(out,"%s",error);
  490.             return -1;
  491.         }
  492.         return 0;
  493.     }
  494.     else {
  495.         sprintf(errstr,"unknown parameter %s to tag %s in %s",
  496.                 tag,directive,file);
  497.         log_error_noclose(errstr);
  498.         bytes_sent += fprintf(out,"%s",error);
  499.         return -1;
  500.     }
  501. }
  502.  
  503.  
  504. int handle_fsize(FILE *in, FILE *out, char *file, char *error, int sizefmt) 
  505. {
  506.     char tag[MAX_STRING_LEN];
  507.     char *tag_val;
  508.     struct stat finfo;
  509.  
  510.     while(1) {
  511.         if(!(tag_val = get_tag(in,tag)))
  512.             return 1;
  513.         else if(!strcmp(tag,"done"))
  514.             return 0;
  515.         else if(!find_file(out,file,"fsize",tag,tag_val,&finfo,error)) {
  516.             if(sizefmt == SIZEFMT_KMG) {
  517.                 send_size(finfo.st_size,out);
  518.                 bytes_sent += 5;
  519.             }
  520.             else {
  521.                 int l,x;
  522.                 sprintf(tag,"%ld",finfo.st_size);
  523.                 l = strlen(tag); /* grrr */
  524.                 for(x=0;x<l;x++) {
  525.                     if(x && (!((l-x) % 3))) {
  526.                         fputc(',',out);
  527.                         ++bytes_sent;
  528.                     }
  529.                     fputc(tag[x],out);
  530.                     ++bytes_sent;
  531.                 }
  532.             }
  533.         }
  534.     }
  535. }
  536.  
  537. int handle_flastmod(FILE *in, FILE *out, char *file, char *error, char *tf) 
  538. {
  539.     char tag[MAX_STRING_LEN];
  540.     char *tag_val;
  541.     struct stat finfo;
  542.  
  543.     while(1) {
  544.         if(!(tag_val = get_tag(in,tag)))
  545.             return 1;
  546.         else if(!strcmp(tag,"done"))
  547.             return 0;
  548.         else if(!find_file(out,file,"flastmod",tag,tag_val,&finfo,error))
  549.             bytes_sent += fprintf(out,"%s",ht_time(finfo.st_mtime,tf,0));
  550.     }
  551. }    
  552.  
  553.  
  554.  
  555. /* -------------------------- The main function --------------------------- */
  556.  
  557. /* This is a stub which parses a file descriptor. */
  558.  
  559. void send_parsed_content(char *file, FILE *f, FILE *fd, 
  560.                          char *path_args, char *args,
  561.                          char **env,int noexec)
  562. {
  563.     char directive[MAX_STRING_LEN], error[MAX_STRING_LEN];
  564.     char timefmt[MAX_STRING_LEN], errstr[MAX_STRING_LEN];
  565.     int ret, sizefmt;
  566.  
  567.     strcpy(error,DEFAULT_ERROR_MSG);
  568.     strcpy(timefmt,DEFAULT_TIME_FORMAT);
  569.     sizefmt = SIZEFMT_KMG;
  570.  
  571.     chdir_file(file);
  572.  
  573.     while(1) {
  574.         if(!find_string(f,STARTING_SEQUENCE,fd)) {
  575.             if(get_directive(f,directive))
  576.                 return;
  577.             if(!strcmp(directive,"exec")) {
  578.                 if(noexec) {
  579.                     sprintf(errstr,"httpd: exec used but not allowed in %s",
  580.                             file);
  581.                     log_error_noclose(errstr);
  582.                     bytes_sent += fprintf(fd,"%s",error);
  583.                     ret = find_string(f,ENDING_SEQUENCE,NULL);
  584.                 } else 
  585.                     ret=handle_exec(f,fd,file,path_args,args,error,env);
  586.             } 
  587.             else if(!strcmp(directive,"config"))
  588.                 ret=handle_config(f,fd,file,error,timefmt,&sizefmt,env);
  589.             else if(!strcmp(directive,"include"))
  590.                 ret=handle_include(f,fd,file,env,error);
  591.             else if(!strcmp(directive,"echo"))
  592.                 ret=handle_echo(f,fd,file,error,env);
  593.             else if(!strcmp(directive,"fsize"))
  594.                 ret=handle_fsize(f,fd,file,error,sizefmt);
  595.             else if(!strcmp(directive,"flastmod"))
  596.                 ret=handle_flastmod(f,fd,file,error,timefmt);
  597.             else {
  598.                 sprintf(errstr,"httpd: unknown directive %s in parsed doc %s",
  599.                         directive,file);
  600.                 log_error_noclose(errstr);
  601.                 bytes_sent += fprintf(fd,"%s",error);
  602.                 ret=find_string(f,ENDING_SEQUENCE,NULL);
  603.             }
  604.             if(ret) {
  605.                 sprintf(errstr,"httpd: premature EOF in parsed file %s",file);
  606.                 log_error_noclose(errstr);
  607.                 return;
  608.             }
  609.         } else 
  610.             return;
  611.     }
  612. }
  613.  
  614. /* Called by send_file */
  615.  
  616. void send_parsed_file(char *file, FILE *fd, char *path_args, char *args,
  617.                       int noexec) 
  618. {
  619.     FILE *f;
  620.  
  621.     if(!(f=fopen(file,"r"))) {
  622.         log_reason("file permissions deny server access",file);
  623.         unmunge_name(file);
  624.         die(FORBIDDEN,file,fd);
  625.     }
  626.     strcpy(content_type,"text/html");
  627.     if(!assbackwards)
  628.         send_http_header(fd);
  629.     if(header_only) {
  630.     fclose(f);
  631.         return;
  632.     }
  633.  
  634.     /* Make sure no children inherit our buffers */
  635.     fflush(fd);
  636.     assbackwards = 1; /* make sure no headers get inserted anymore */
  637.     alarm(timeout);
  638.  
  639.     in_headers_env = add_include_vars(in_headers_env,file,path_args,args,
  640.                            DEFAULT_TIME_FORMAT,fd);
  641.  
  642.     in_headers_env = add_common_vars(in_headers_env,fd);
  643.  
  644.     send_parsed_content(file,f,fd,path_args,args,in_headers_env,noexec);
  645.     free_env(in_headers_env);
  646.     in_headers_env = NULL;
  647. }
  648.